/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "物体编辑.h"
#include "A_引擎/引擎.h"
#include "B_场景管理/操作记录.h"


#include <场景/intern/S_Scene.h>
#include <物体编辑/编辑骨骼.h>

#include "框架/工作区/工作区.h"
#include "框架/工作区/大纲/ui大纲视图.h"

#include "物体管理/渲染物体管理.h"
#include "物体管理/渲染物体创建销毁.h"

#include "3D控制手柄.h"



class C_物体移动变换记录 : public C_操作记录 {
	std::vector<S_物体*> m_物体;
	std::vector<S_Tranform> m_完成前变换;
	std::vector<S_Tranform> m_完成后变换;

	S_Tranform m_完成前手柄坐标;
	S_Tranform m_完成后手柄坐标;
public:
	
	C_物体移动变换记录(std::set<S_物体*>& ob, E_编辑操作类型 操作类型) : C_操作记录(操作类型) {
		m_物体.reserve(ob.size());
		m_完成前变换.reserve(ob.size());
		for (auto& e : ob) {
			m_完成前变换.emplace_back(e->m_变换);
			m_物体.emplace_back(e);
		}

		m_完成前手柄坐标 = S_框架::g_变换手柄属性;
	}
	~C_物体移动变换记录() {
		
	}

	uint8 f_重做() {

		if (m_完成后变换.size() == m_物体.size()) {
			uint32 i = 0;

			for (auto& e : m_物体) {
				e->m_变换 = m_完成后变换[i];
				e->m_isUpdate = true;
				++i;
			}
		}
		//S_框架::g_移动变换手柄->f_set位置(m_完成后手柄坐标);
		S_框架::g_变换手柄属性 = m_完成后手柄坐标;
		f_控制手柄_置变换();

		f_工作区_联动更新(E_工作区类型::e_3D视口, E_工作区操作类型::e_变换物体);
		return C_操作记录::f_重做();
	}

	uint8 f_撤销() {
		uint32 i = 0;
		for (auto& e : m_物体) {
			e->m_变换 = m_完成前变换[i];
			e->m_isUpdate = true;
			++i;
		}

		//S_框架::g_移动变换手柄->f_set位置(m_完成前手柄坐标);
		S_框架::g_变换手柄属性 = m_完成前手柄坐标;
		f_控制手柄_置变换();

		f_工作区_联动更新(E_工作区类型::e_3D视口, E_工作区操作类型::e_变换物体);
		return C_操作记录::f_撤销();
	}
	
	void f_完成记录() {
		for (auto& e : m_物体) {
			m_完成后变换.emplace_back(e->m_变换);

			if (m_操作类型 == E_编辑操作类型::e_操作类型_变换旋转) {
				//e->m_包围盒 = f_me_计算物体包围盒(e->m_Bound, e->m_旋转矩阵);
			}
		}
		m_完成后手柄坐标 = S_框架::g_变换手柄属性;

		DEF_记录日志("变换物体:" + std::to_string(m_物体.size()) );
	}
};


static C_物体移动变换记录* g当前操作记录 = nullptr;



void f_global_set切换物体编辑模式(S_Props& prop) {
	
	switch (f_prop_enum(prop)) {
		case E_网格编辑模式::e_网格编辑_顶点: {
			
			f_NodeCtx_clear选中编辑物体();
			for (auto& e : S_框架::g_拾取物体) {
				f_NodeCtx_set选中编辑物体(e, 0, true);
			}

			switch (S_框架::g当前编辑对象类型) {
				case E_物体类型::t_空间曲线: {
					for (auto& e : S_节点数据::g_编辑物体) {
						f_ob_getMesh(e, 1)->m_显示 = true;
						f_ob_getMesh(e, 2)->m_显示 = true;
					}
					break;
				}
			}
			break;
		}

		case E_网格编辑模式::e_网格编辑_权重: {
			switch (S_框架::g当前编辑对象类型) {
				
				case E_物体类型::t_多边形:
				case E_物体类型::t_网格物体: {
					for (auto& e : S_框架::g_拾取物体) {
						f_node_设置物体权重材质(e);
						f_ob_getMesh(e, E_物体网格元素类型::e_MT_面)->m_片源着色模式 = DEF_DrawType_Weigth;
					}
					break;
				}
				case E_物体类型::t_空间曲线:
				case E_物体类型::t_骨架:
				case E_物体类型::t_骨骼: {
					break;
				}

				case E_物体类型::t_摄像机: {
					break;
				}
				default:
					break;
			}

			break;
		}

		case E_网格编辑模式::e_网格编辑_纹理: {
			break;
		}

		default:
			switch (S_框架::g当前编辑对象类型) {
				case E_物体类型::t_网格物体: 
				case E_物体类型::t_多边形: {
					for (auto& e : S_框架::g_拾取物体) {
						f_node_设置物体光照材质(e);
						f_ob_getMesh(e, E_物体网格元素类型::e_MT_面)->m_片源着色模式 = DEF_DrawType_LS;
					}

					f_NodeCtx_set物体全局显示模式(E_物体渲染模式(S_节点数据::g_物体全局渲染模式));
					break;
				}
				case E_物体类型::t_空间曲线: {
					for (auto& e : S_节点数据::g_编辑物体) {
						f_ob_getMesh(e, 1)->m_显示 = false;
						f_ob_getMesh(e, 2)->m_显示 = false;
					}
					break;
				}
			}

			f_NodeCtx_clear选中编辑物体();
			f_prop_Bool(S_节点数据状态::g_是否打开了编辑模式) = false;
			return;
	}

	f_prop_Bool(S_节点数据状态::g_是否打开了编辑模式) = true;

	//switch (f_prop_enum(prop)) {
	//	case E_物体编辑模式::e_物体编辑: {
	//		break;
	//	}
	//	case E_物体编辑模式::e_网格编辑: {
	//		
	//		break;
	//	}
	//	case E_物体编辑模式::e_权重绘制: {
	//		switch (S_框架::g当前编辑对象类型) {
	//
	//		}
	//		break;
	//	}
	//	case E_物体编辑模式::e_纹理绘制: {
	//		break;
	//	}
	//	default:
	//		break;
	//}


}

void f_OE_开始拾取点初始化(S_摄像机* camera, const vec2& 鼠标局部位置, const S_Rect2Df& rect) {
	vec3 坐标 = { 鼠标局部位置.x, 鼠标局部位置.y, 0.0f };
	vec3 当前射线[2];
	当前射线[0] = f_NodeCtx_get默认场景()->f_get屏幕坐标到空间(camera, 坐标, rect);
	坐标.z = 1.0;
	当前射线[1] = f_NodeCtx_get默认场景()->f_get屏幕坐标到空间(camera, 坐标, rect);
	S_射线拾取参数::g结束射线 = vec_normalize2(当前射线[1] - 当前射线[0]);

	vec3 视线向量 = f_camera_get视线向量(*camera);
	switch (S_框架::g_操作变换轴) {
	case E_轴向::e_X: vec_mul(&视线向量, vec3{ 0, 1, 1 }); break;
	case E_轴向::e_Y: vec_mul(&视线向量, vec3{ 1, 0, 1 }); break;
	case E_轴向::e_Z: vec_mul(&视线向量, vec3{ 1, 1, 0 }); break;
	default:
		break;
	}
	vec_normalize(视线向量);
	//f_graph_射线相交平面(当前射线[0] - S_射线拾取参数::g手柄初始变换, 当前射线[1] - S_射线拾取参数::g手柄初始变换, 视线向量, S_射线拾取参数::g交点S);
}


//void f_OE_准备移动(C_Widget* self, S_摄像机* camera) {
//	S_框架::g_变换开关 = true;
//	S_框架::g_操作变换轴 = E_轴向::e_XYZ;
//	S_框架::g_物体变换方式 = E_变换::e_移动;
//	S_框架::g_视线向量 = f_camera_get视线向量(*camera);
//	S_射线拾取参数::g手柄初始变换 = S_框架::g_变换手柄属性.position;
//	
//	S_框架::g_鼠标起始坐标 = f_widget_get鼠标局部位置(C_Widget::g_鼠标.gPos, self);
//	f_OE_开始拾取点初始化(camera, S_框架::g_鼠标起始坐标, f_ui_get视口(self));
//}


void f_OE_骨骼姿态编辑模式切换(S_Props& prop) {

}

void f_OE_移动后更新(std::vector<S_物体*>& obs) {
	
	if (f_prop_Bool(S_节点数据状态::g_是否打开了编辑模式)){
		switch (S_框架::g当前编辑对象类型) {
			case E_物体类型::t_网格物体:
				break;

			case E_物体类型::t_骨架:
			case E_物体类型::t_骨骼: {
				switch (f_prop_enum(S_节点数据状态::g_骨架编辑模式)) {
					case E_骨骼编辑模式::e_骨架模式: {
						break;
					}

					case E_骨骼编辑模式::e_编辑模式: {
						
						for (auto* ob : S_框架::g_拾取物体) {
							if (ob->m_Type == E_物体类型::t_骨架) {
								f_OE_更新骨骼封套范围线绘制(ob);
							}
						}

						break;
					}

					case E_骨骼编辑模式::e_姿态模式: {
						break;
					}
				}
				break;
			}
			case E_物体类型::t_灯光:
				break;
			default:
				break;
		}
	}
	else {
		const auto& planes = f_NodeCtx_从可视物体取节点(obs);
		for (auto& e : planes) {
			e->f_set是否要更新(true);
		}
	}

}

void f_OE_旋转后更新(std::vector<S_物体*>& obs) {
	if (f_prop_Bool(S_节点数据状态::g_是否打开了编辑模式)) {
		switch (S_框架::g当前编辑对象类型) {
			case E_物体类型::t_网格物体:

				break;
			case E_物体类型::t_骨架:
			case E_物体类型::t_骨骼: {
				switch (f_prop_enum(S_节点数据状态::g_骨架编辑模式)) {
					case E_骨骼编辑模式::e_骨架模式: {
						break;
					}
					case E_骨骼编辑模式::e_编辑模式: {
						const auto& planes = f_NodeCtx_从可视物体取节点(obs);
						for (auto& e : planes) {
							e->f_set是否要更新(1);
						}

						break;
					}
			
					case E_骨骼编辑模式::e_姿态模式: {
						break;
					}
				}
				break;
			}

			case E_物体类型::t_虚拟体: {
				break;
			}
			case E_物体类型::t_摄像机: {
				break;
			}
			case E_物体类型::t_灯光:

				break;
			default:
				break;
		}
	}
	else {
		const auto& planes = f_NodeCtx_从可视物体取节点(obs);
		for (auto& e : planes) {
			e->f_set是否要更新(true);
		}
	}
}

void f_OE_缩放后更新(std::vector<S_物体*>& obs) {
	//auto& planes = f_global_get激活节点();
	const auto& planes = f_NodeCtx_从可视物体取节点(obs);
	for (auto& e : planes) {
		e->f_set是否要更新(true);
	}

	if (f_prop_Bool(S_节点数据状态::g_是否打开了编辑模式) == false) return;
}



void f_OE_准备变换(std::set<S_物体*>& obs, uint32 变换类型) {
	g当前操作记录 = new C_物体移动变换记录(obs, E_编辑操作类型(变换类型));
}

void f_OE_变换完成() {
	if (g当前操作记录) {
		g当前操作记录->f_完成记录();
	}
	g当前操作记录 = nullptr;
}

void f_OE_变换取消() {
	
}





void f_OE_物体变换插帧(uint32 变换类型) {
	S_时间帧& 帧 = f_NodeCtx_get帧();
	int32 tiem = 帧.当前帧;

	vec2 value;
	value.x = tiem;

	S_RGBA8UI color[3] = {
		{255,60,60,255},
		{60,255,60,255},
		{60,60,255,255},
	};
	if (变换类型 & 1) {
		for (auto& e : S_框架::g_拾取物体) {
			if (!(e->m_位置)) e->m_位置 = f_an_创建曲线通道(3);

			float32* v = (float32*)&(e->m_变换.position);
			for (int32 i = 0; i < e->m_位置->count; ++i) {
				uint32 id = e->m_位置->曲线[i]->count;

				value.y = v[i];
				//vec2 value_L;
				//vec2 value_R;
				int32 重叠索引 = f_an_查找重叠帧(e->m_位置->曲线[i], value.x);
				if (重叠索引 < 0) {
					f_an_添加曲线点(e->m_位置->曲线[i], value, {}, {}, id, color[i]);
				}
				else {
					e->m_位置->曲线[i]->point[重叠索引].value = value;
				}
				f_an_曲线值排序(e->m_位置->曲线[i]);
				f_an_自动控制点(e->m_位置->曲线[i]);
			}
			e->m_isUpdate = true;
		}
	}

	if (变换类型 & 2) {
		for (auto& e : S_框架::g_拾取物体) {
			if (!(e->m_旋转)) e->m_旋转 = f_an_创建曲线通道(3);

			float32* v = (float32*)&(e->m_变换.rotation);
			for (int32 i = 0; i < e->m_旋转->count; ++i) {
				uint32 id = e->m_旋转->曲线[i]->count;

				value.y = v[i];
				int32 重叠索引 = f_an_查找重叠帧(e->m_旋转->曲线[i], value.x);
				if (重叠索引 < 0) {
					f_an_添加曲线点(e->m_旋转->曲线[i], value, {}, {}, id, color[i]);
				}
				else {
					e->m_旋转->曲线[i]->point[重叠索引].value = value;
				}
				f_an_曲线值排序(e->m_旋转->曲线[i]);
				f_an_自动控制点(e->m_旋转->曲线[i]);
			}
			e->m_isUpdate = true;
		}
	}

	if (变换类型 & 4) {
		for (auto& e : S_框架::g_拾取物体) {
			if (!(e->m_缩放)) e->m_缩放 = f_an_创建曲线通道(3);

			float32* v = (float32*)&(e->m_变换.scale);
			for (int32 i = 0; i < e->m_缩放->count; ++i) {
				uint32 id = e->m_缩放->曲线[i]->count;

				value.y = v[i];
				int32 重叠索引 = f_an_查找重叠帧(e->m_缩放->曲线[i], value.x);
				if (重叠索引 < 0) {
					f_an_添加曲线点(e->m_缩放->曲线[i], value, {}, {}, id, color[i]);
				}
				else {
					e->m_缩放->曲线[i]->point[重叠索引].value = value;
				}
				f_an_曲线值排序(e->m_缩放->曲线[i]);
				f_an_自动控制点(e->m_缩放->曲线[i]);
			}
			e->m_isUpdate = true;
		}
	}


	switch (变换类型) {
	case E_变换::e_移动: {
		break;
	}
	case E_变换::e_旋转: {
		break;
	}
	case E_变换::e_缩放: {
		break;
	}
	default:
		break;
	}
}



void f_OE_物体添加到渲染层(S_Object* 渲染层, const std::set<S_物体*>& obs) {
	S_渲染层* 渲染层对象 = (S_渲染层*)渲染层->m_UserData;
	for (auto& e : obs) {
		if (渲染层对象->m_渲染物体映射.find(e) == 渲染层对象->m_渲染物体映射.end()) {
			S_渲染对象* 渲染对象 = new S_渲染对象();
			渲染对象->m_物体 = e;
			渲染对象->m_Name = e->m_Name;
			渲染层->m_子物体.push_back(渲染对象);

			渲染对象->m_父对象 = 渲染层;

			渲染层对象->m_渲染物体映射.insert(e);
		}
	}
}

void f_OE_物体添加到渲染层(S_Object* 渲染层, const std::vector<S_渲染对象*>& obs) {
	S_渲染层* 渲染层对象 = (S_渲染层*)渲染层->m_UserData;

	for (auto& e : obs) {
		e->m_父对象 = 渲染层;
		渲染层->m_子物体.push_back(e);

		渲染层对象->m_渲染物体映射.insert(e->m_物体);
	}
}

void f_OE_物体从渲染层移除(S_Object* 渲染层, S_渲染对象** obs, uint32 num) {
	S_渲染层* 渲染层对象 = (S_渲染层*)渲染层->m_UserData;

	for (uint32 i = 0; i < num; ++i) {
		for (auto it = 渲染层->m_子物体.begin(); it != 渲染层->m_子物体.end(); ++it) {
			if ((*it) == obs[i]) {
				渲染层对象->m_渲染物体映射.erase(obs[i]->m_物体);

				delete (*it);
				渲染层->m_子物体.erase(it);
				break;
			}
		}
	}
}




class C_物体复制操作 : public C_操作记录 {
	std::set<S_物体*> m_物体;
	std::set<S_物体*> m_新物体;

	bool m_链接;
public:

	C_物体复制操作(std::set<S_物体*>& obs, bool 链接) : C_操作记录(E_编辑操作类型::e_操作类型_添加物体) {
		m_物体 = obs;
		m_链接 = 链接;
		
		uint32 i = 0;

		for (auto& e : m_物体) {
			S_物体* ob = f_ob_copy(e->m_Ctx, e, m_链接);
			if (!m_链接) {
				f_OB_复制网格物体数据(ob, e);
			}

			ob->m_Name = f_global_渲染物体键值().f_Gen(e->m_Name);
			ob->m_isUpdate = true;

			
			m_新物体.insert(ob);
			++i;
		}
		f_OE_更新网格包围盒(m_新物体);

		f_重做();
	}
	~C_物体复制操作() {
		
	}

	uint8 f_重做() {
		for (auto& e : m_新物体) {
			f_global_渲染物体()[e->m_Name] = e;
		}
		S_框架::g_拾取物体 = m_新物体;
		
		std::set<S_Object*> item(m_新物体.begin(), m_新物体.end());
		f_大纲视图_添加对象(item);

		f_工作区_联动更新(E_工作区类型::e_3D视口, E_工作区操作类型::e_创建物体);
		DEF_记录日志("复制物体:" + std::to_string(m_新物体.size()) );
		return C_操作记录::f_重做();
	}

	uint8 f_撤销() {
		for (auto& e : m_新物体) {
			f_global_渲染物体().erase(e->m_Name);
		}
		S_框架::g_拾取物体 = m_物体;

		std::set<S_Object*> item(m_新物体.begin(), m_新物体.end());
		f_大纲视图_删除对象(item);

		f_工作区_联动更新(E_工作区类型::e_3D视口, E_工作区操作类型::e_删除物体);
		DEF_记录日志("撤销物体:" + std::to_string(m_新物体.size()) );
		return C_操作记录::f_撤销();
	}
	
};

void f_OE_复制(std::set<S_物体*>& obs, bool 链接) {
	auto 物体复制操作 = new C_物体复制操作(obs, 链接);
	物体复制操作->f_执行步数(0, 1);

}

void f_OE_更新网格包围盒(const std::set<S_物体*>& obs) {
	for (auto& e : obs) {
		f_ob_添加更新缓存列队(std::make_unique<C_物体缓存列队数据>(e));

		//auto& 面 = f_ob_get数据(e, 0);
		//auto& 框 = f_ob_get数据(e, 3);
		//
		//e->m_Bound = f_mesh_计算包围盒(面.m_Mesh, nullptr);
		//auto boundSize = e->m_Bound.max - e->m_Bound.min;
		//f_me_fill顶点(框.m_Mesh, {S_VNTC{e->m_Bound.min + boundSize*0.5f, boundSize,{}}});
	}
}






